/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */

#ifndef __PQ_GameBuilder_H__
#define __PQ_GameBuilder_H__

#include "SceneCamera.h"
#include "InputOpTranslator.h"
#include "TransformGizmo.h"

namespace PQBuilder
{
#define OBJECT_FRAME_DISTANCE 10
#define  BUILDER_RENDER_WINDOW_NAME "GameBuilderRenderWindow"
	class SceneDragEvent
	{
	public:
		int x;
		int y;
		char* data;//data with drag
		int len;//data length with drag
	public:
		SceneDragEvent(int x0=0,int y0=0,char* data0=0,int len0=0)
			:x(x0),y(y0),data(data0),len(len0){}
		
	};

	enum SceneOperation
	{
		SCENE_OPERATION_CLOSED,//set indicate not in time duration operation
		SCENE_OPERATION_START_TRANSFORM,

	};


	/** Class used to manage the game builder.
        @remarks
			This is core class of the whole game build system.
			Should build an event system in this level.
    */
	class GameBuilder
	{
	public:
		/*Game Build Scene edit mode
		@remark The game builder state at a specific edit state.
		*/
		enum EditMode
		{
			GEDIT_MODE_SELECT,
			GEDIT_MODE_TRANSLATE_OBJECT,
			GEDIT_MODE_ROTATE_OBJECT,
			GEDIT_MODE_SCALE_OBJECT,
		};

		GameBuilder();

		~GameBuilder();
		

		PQEngine::Object* addGPKResource(std::string path);
		PQEngine::Object* createObject(PQEngine::ObjectType type);

		void init(Ogre::String wnd,int width,int height);

		void renderOneFrame();

		void activate();

		void createDefaultScene();
		void loadScene();
		
		/*Select and frame game object with specified id.
		@param id The game object's id.
		*/
		void selectAndFrameObject(int id);

		/*Get scene render property.
		Use this can also set render property.
		*/
		PQEngine::SceneRenderProperty& getRenderProperty();

		//deltaT in second
		void update(float deltaT);

		void startGameEngine();

		inline EditMode getEditMode()
		{
			return _mode;
		}

		/*Create a flat terrain chunk in position slotX slotY with diffuse texture index in terrain texture GPK archive.
		@param slotX The X coord of slot position.
		@param slotX The Y coord of slot position.
		@param diffuseTexIndex The diffuse texture index in terrain texture GPK archive.
		*/
		void createFlatTerrain(int slotX,int slotY,int diffuseTexIndex);
	private:
		/*Process Operations produced by input translator.
		*/
		void processOps(int x,int y);

		/*Try to close last time duration scene edit operation.
		Return true if stop the time duration operation.
		*/
		bool closeOperation();
		/*Process operations and return true if processed.
		*/
		bool processGeneralOps(int x,int y);
		bool processObjectOps(int x,int y);
		bool processTerrainOps(int x,int y);

		/*Select operation is very special.Should we be process left mouse button down is better.
		When select a gizmo axis in transform mode,We should tranform the object.
		*/
		void processSelectOp();

		void changeEditMode(EditMode mode);
		void exec(char* data,int len);
	private:
		Ogre::Root* _root;//ogre root;//bool _inited;
		Ogre::RenderWindow* _renderWindow;//

		PQEngine::SceneObject* _sceneObject;//
		PQEngine::GameObject* _dragObject;//current dragging object
		TransformGizmo* _axisGizmo;
		SceneCamera* _sceneCamera;
		EditMode _mode;
		SceneOperation _operation;
		InputOpTranslator* _translator;
		bool _playing;//is game playing?
		int _mouseX;
		int _mouseY;//current frame mouse position
		int _lastMouseX;//last frame mouse position
		int _lastMouseY;
	public:
		//Input methods
		void ResetScreenResolution(int width,int height);//
		void ResetInput();

		void OnKeyDown(int key);
		void OnKeyUp(int key);
		
		void OnMouseLeftDown(int x,int y);
		void OnMouseLeftUp(int x,int y);

		void OnMouseRightDown(int x,int y);
		void OnMouseRightUp(int x,int y);

		void OnMouseMidDown(int x,int y);
		void OnMouseMidUp(int x,int y);

		void OnMouseMove(int x,int y);

		void OnDragEnter(SceneDragEvent evt);
		void OnDragMove(SceneDragEvent evt);
		void OnDrop(SceneDragEvent evt);

		void enableSkyDome(bool enabled);
		void defineResource();
	};

}

#endif
